package taskrunner

import "log"

type Runner struct {
	Controller controlChan
	//专门用于返回CLOSE信息
	Error controlChan
	//实际数据的交换管道
	Data     dataChan
	dataSize int
	//是否是常驻任务
	longlived bool

	Dispatcher fn
	Executer   fn
}

func NewRunner(size int, longlived bool, dispatcher fn, executer fn) *Runner {
	return &Runner{
		dataSize:   size,
		longlived:  longlived,
		Dispatcher: dispatcher,
		Executer:   executer,
		Controller: make(chan string, 1),
		Error:      make(chan string, 1),
		Data:       make(chan interface{}, size),
	}
}

func (r *Runner) startDispatch() {
	defer func() {
		//如果不是常驻的runner，则收到CLOSE之后
		//关闭所有相关channel
		if !r.longlived {
			close(r.Controller)
			close(r.Data)
			close(r.Error)
		}
	}()

	for {
		select {
		case c := <-r.Controller:
			if c == READY_TO_DISPATCH {
				//收到READY_TO_DISPATCH后
				//调用Dispatcher方法 往r.Data中写入数据
				log.Println("收到READY_TO_DISPATCH")
				if err := r.Dispatcher(r.Data); err != nil {
					log.Println("Dispatcher错误："+err.Error())
					r.Error <- CLOSE
				} else {
					//如果Dispatcher执行成功，则准备执行
					r.Controller <- READY_TO_EXECUTE
				}
				continue
			}

			if c == READY_TO_EXECUTE {
				log.Println("READY_TO_EXECUTE")
				if err := r.Executer(r.Data); err != nil {
					r.Error <- CLOSE
				} else {
					r.Controller <- READY_TO_DISPATCH
				}
			}
		case e := <-r.Error:
			//从Error获取关闭信息
			if e == CLOSE {
				return
			}
		default: //controller和error均无数据

		}
	}
}

//开始Runner
func (r *Runner) StartAll() {
	//最开始Runner中的管道是无数据的，因此需要一开始先放一个
	r.Controller <- READY_TO_DISPATCH
	r.startDispatch()
}
